<?php


class APriority
{
	/**
    *   Moves file (one position), which has ID and PRIORITY fields, up. Method changes file and all relative PRIORITY
    *   @param $c Criteria initialized Criteria object, which extracts neccessary files for object
    *   @param $idToUp integer ID of file to move up
    */
    public static function moveUp($c, $idToUp)
    {
        // Proceed if got table name from Criteria object
        if( ($table = APriority::getTableFromCriteria($c)) )
        {
            $connection = Propel::getConnection();

            // Selecting only ID and priority fields from table, order by priority
            $c->clearSelectColumns();
            $c->clearOrderByColumns();
            $c->addSelectColumn('id');
            $c->addSelectColumn('priority');
            $c->addDescendingOrderByColumn('priority');
            $arObj = BasePeer::doSelect($c);

            // Put objects as simple array: [0] => ID, [1] => PRIORITY
            $ar = array();
            foreach( $arObj as $obj )
                $ar[] = array( $obj[0], $obj[1] );
            
            //APriority::debugAr($ar);

            $pos = APriority::findPositionOfObject($ar, $idToUp);
            //debugvar('Position of obj ID to move is: ' . $pos);

            // If object is not the first
            if( $pos > 0 )
            {
                // Move object up
                // set objects with given id ($idToUp) priority one greather then one position higher element 
                $priority = $ar[$pos - 1][1] + 1;
                $obj = $ar[$pos];
                $ar[$pos] = $ar[$pos - 1];
                $ar[$pos - 1] = $obj;

                $ar[$pos -1][1] = $priority;
                $query = sprintf(
                            'UPDATE `%s` SET `priority` = %d WHERE `id` = %d LIMIT 1'
                            , $table
                            , $priority
                            , $ar[$pos -1][0]
                        );
                    $statement = $connection->prepareStatement($query);
                    $statement->executeQuery();
                    //debugvar($table . ' TABLE ' . $priority . ' Priority ' . $ar[$i][0] . ' id');
                //APriority::debugAr($ar);

                // Lowest priority
                //$priority = $ar[$pos][1];
                //debugvar('Lowest priority: ' . $priority);
                if( !empty($ar[$pos - 2]) )
                {
	                for( $i = $pos - 2; $i >= 0; $i-- )
	                {
	                    // Increase priority if higher object has smaller priority
	                    if(!(($ar[$i][1] - $ar[$i + 1][1])>1))
	                    {
	                        $ar[$i][1] = $ar[$i + 1][1] + 1;
	                    }
	                    $query = sprintf(
	                            'UPDATE `%s` SET `priority` = %d WHERE `id` = %d LIMIT 1'
	                            , $table
	                            , $ar[$i][1]
	                            , $ar[$i][0]
	                        );
	                    $statement = $connection->prepareStatement($query);
	                    $statement->executeQuery();
	                }
                }
               // APriority::debugAr($ar);
            }elseif( $pos == 0 )
            {
                debugvar('Already first');
            }else
            {
            }

            //APriority::debugAr($ar);

        }

        //exit('sorting...');
    }

    /**
    *   Normalize priority fields, makes PRIORITY in table to start from 1
    *   @param $c Criteria initialized Criteria object, which extracts neccessary files for object
    */
    public static function normalizePriority($c)
    {
        // Proceed if got table name from Criteria object
        if( ($table = APriority::getTableFromCriteria($c)) )
        {

            $connection = Propel::getConnection();

            // Selecting only ID and priority fields from table, order by priority
            $c->clearSelectColumns();
            $c->clearOrderByColumns();
            $c->addSelectColumn('id');
            $c->addSelectColumn('priority');
            $c->addAscendingOrderByColumn('priority');
            $ar = BasePeer::doSelect($c);
            $priority = 1;
            foreach($ar as $obj)
            {

                $query = sprintf(
                    'UPDATE `%s` SET `priority` = %d WHERE `id` = %d LIMIT 1'
                    , $table
                    , $priority
                    , $obj[0]
                );
                $statement = $connection->prepareStatement($query);
                $statement->executeQuery();

                //debugvar($query);
                $priority++;
            }
        }

        //exit('normalization is done...');
    }

    /**
    *   Moves file, which has ID and PRIORITY fields, up. Method changes file and all relative PRIORITY
    *   @param $c Criteria initialized Criteria object, which extracts neccessary files for object
    *   @param $idToUp integer ID of file to move up
    */
    public static function _moveUp_($c, $idToUp)
    {
        // Proceed if got table name from Criteria object
        if( ($table = APriority::getTableFromCriteria($c)) )
        {
            $connection = Propel::getConnection();

            // Selecting only ID and priority fields from table, order by priority
            $c->clearSelectColumns();
            $c->clearOrderByColumns();
            $c->addSelectColumn('id');
            $c->addSelectColumn('priority');
            $c->addDescendingOrderByColumn('priority');
            $arObj = BasePeer::doSelect($c);

            // Put objects as simple array: [0] => ID, [1] => PRIORITY
            $ar = array();
            foreach( $arObj as $obj )
                $ar[] = array( $obj[0], $obj[1] );
            
            APriority::debugAr($ar);

            $pos = APriority::findPositionOfObject($ar, $idToUp);
            debugvar('Position of obj ID to move is: ' . $pos);

            // If object is not the first
            if( $pos > 0 )
            {
                // Move object up
                $obj = $ar[$pos];
                $ar[$pos] = $ar[$pos - 1];
                $ar[$pos - 1] = $obj;

                APriority::debugAr($ar);

                // Lowest priority
                $priority = $ar[$pos][1];
                //debugvar('Lowest priority: ' . $priority);

                for( $i = $pos - 1; $i >= 0; $i-- )
                {
                    // Increase priority if higher object has smaller priority
                    if( $ar[$i][1] <= $priority )
                    {
                        $priority++;
                        $ar[$i][1] = $priority;
                        $query = sprintf(
                            'UPDATE `%s` SET `priority` = %d WHERE `id` = %d LIMIT 1'
                            , $table
                            , $priority
                            , $obj[0]
                        );

                        //debugvar('Changing priority: ' . $query);
                        $statement = $connection->prepareStatement($query);
                        $statement->executeQuery();

                    }else
                        $priority++;
                }

            }elseif( $pos == 0 )
            {
                debugvar('Already first');
            }else
            {
            }

            APriority::debugAr($ar);

        }

        //exit('sorting...');
    }

    /**
    *   Returns name of table from Criteria object
    *   @return string name of table or empty string
    */
    public static function getTableFromCriteria($c)
    {
        $table = '';
         $arTables = $c->getTablesColumns();
        //debugvar($arTables);
        if( !empty($arTables) )
        {
            list($table) = each($arTables);
        }

        return $table;
    }

    protected static function debugAr($ar)
    {
        for($i = 0; $i < count($ar); $i++)
            debugvar($i . ': ' . $ar[$i][0] . ' ' . $ar[$i][1]);
    }


    protected static function findPositionOfObject($ar, $idToUp)
    {
        $pos = -1;
        $i = 0;
        $totalR = count($ar);
        debugvar('Searching for ID to move up: ' . $idToUp);
        // Get position in sorted array
        while( ($pos < 0) && ($i < $totalR) )
        {
            if( $ar[$i][0] == $idToUp )
                $pos = $i;
            $i++;
        }

        return $pos;
    }


}